// Copyright Epic Games, Inc. All Rights Reserved.

#include "GameFeatureAction_AddAbilities.h"
#include "Engine/GameInstance.h"
#include "Components/GameFrameworkComponentManager.h"
#include "AbilitySystem/LyraAbilitySystemComponent.h"
#include "Engine/World.h"
#include "Player/LyraPlayerState.h" //@TODO: 为了FName
#include "GameFeatures/GameFeatureAction_WorldActionBase.h"

#if WITH_EDITOR
#include "Misc/DataValidation.h" // 数据验证相关
#endif

#include UE_INLINE_GENERATED_CPP_BY_NAME(GameFeatureAction_AddAbilities) // 包含自动生成的代码

#define LOCTEXT_NAMESPACE "GameFeatures" // 定义本地化文本命名空间

//////////////////////////////////////////////////////////////////////
// UGameFeatureAction_AddAbilities

/**
 * 游戏特性激活时调用
 */
void UGameFeatureAction_AddAbilities::OnGameFeatureActivating(FGameFeatureActivatingContext& Context)
{
	FPerContextData& ActiveData = ContextData.FindOrAdd(Context); // 查找或添加上下文数据

	if (!ensureAlways(ActiveData.ActiveExtensions.IsEmpty()) || // 确保活跃扩展为空
		!ensureAlways(ActiveData.ComponentRequests.IsEmpty())) // 确保组件请求为空
	{
		Reset(ActiveData); // 重置数据
	}
	Super::OnGameFeatureActivating(Context); // 调用父类方法
}

/**
 * 游戏特性停用时调用
 */
void UGameFeatureAction_AddAbilities::OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context)
{
	Super::OnGameFeatureDeactivating(Context); // 调用父类方法
	FPerContextData* ActiveData = ContextData.Find(Context); // 查找上下文数据

	if (ensure(ActiveData)) // 确保数据有效
	{
		Reset(*ActiveData); // 重置数据
	}
}

#if WITH_EDITOR
/**
 * 数据验证方法
 */
EDataValidationResult UGameFeatureAction_AddAbilities::IsDataValid(FDataValidationContext& Context) const
{
	EDataValidationResult Result = CombineDataValidationResults(Super::IsDataValid(Context), EDataValidationResult::Valid); // 组合数据验证结果

	int32 EntryIndex = 0; // 条目索引
	for (const FGameFeatureAbilitiesEntry& Entry : AbilitiesList) // 遍历能力列表
	{
		if (Entry.ActorClass.IsNull()) // 检查Actor类是否为空
		{
			Result = EDataValidationResult::Invalid; // 设置为无效
			Context.AddError(FText::Format(LOCTEXT("EntryHasNullActor", "AbilitiesList中索引{0}处的ActorClass为空"), FText::AsNumber(EntryIndex))); // 添加错误信息
		}

		if (Entry.GrantedAbilities.IsEmpty() && Entry.GrantedAttributes.IsEmpty() && Entry.GrantedAbilitySets.IsEmpty()) // 检查是否没有任何添加项
		{
			Result = EDataValidationResult::Invalid; // 设置为无效
			Context.AddError(FText::Format(LOCTEXT("EntryHasNoAddOns", "AbilitiesList中索引{0}将不执行任何操作（没有授予的能力、属性或能力集）"), FText::AsNumber(EntryIndex))); // 添加错误信息
		}

		int32 AbilityIndex = 0; // 能力索引
		for (const FLyraAbilityGrant& Ability : Entry.GrantedAbilities) // 遍历授予的能力
		{
			if (Ability.AbilityType.IsNull()) // 检查能力类型是否为空
			{
				Result = EDataValidationResult::Invalid; // 设置为无效
				Context.AddError(FText::Format(LOCTEXT("EntryHasNullAbility", "AbilitiesList[{1}].GrantedAbilities中索引{0}处的AbilityType为空"), FText::AsNumber(AbilityIndex), FText::AsNumber(EntryIndex))); // 添加错误信息
			}
			++AbilityIndex; // 递增能力索引
		}

		int32 AttributesIndex = 0; // 属性索引
		for (const FLyraAttributeSetGrant& Attributes : Entry.GrantedAttributes) // 遍历授予的属性
		{
			if (Attributes.AttributeSetType.IsNull()) // 检查属性集类型是否为空
			{
				Result = EDataValidationResult::Invalid; // 设置为无效
				Context.AddError(FText::Format(LOCTEXT("EntryHasNullAttributeSet", "AbilitiesList[{1}].GrantedAttributes中索引{0}处的AttributeSetType为空"), FText::AsNumber(AttributesIndex), FText::AsNumber(EntryIndex))); // 添加错误信息
			}
			++AttributesIndex; // 递增属性索引
		}

		int32 AttributeSetIndex = 0; // 属性集索引
		for (const TSoftObjectPtr<const ULyraAbilitySet>& AttributeSetPtr : Entry.GrantedAbilitySets) // 遍历授予的能力集
		{
			if (AttributeSetPtr.IsNull()) // 检查能力集是否为空
			{
				Result = EDataValidationResult::Invalid; // 设置为无效
				Context.AddError(FText::Format(LOCTEXT("EntryHasNullAttributeSet", "AbilitiesList[{1}].GrantedAbilitySets中索引{0}处的AbilitySet为空"), FText::AsNumber(AttributeSetIndex), FText::AsNumber(EntryIndex))); // 添加错误信息
			}
			++AttributeSetIndex; // 递增属性集索引
		}
		++EntryIndex; // 递增条目索引
	}

	return Result; // 返回结果

	return EDataValidationResult::NotValidated; // 返回未验证（不会执行到这里）
}
#endif

/**
 * 添加到世界的方法
 */
void UGameFeatureAction_AddAbilities::AddToWorld(const FWorldContext& WorldContext, const FGameFeatureStateChangeContext& ChangeContext)
{
	UWorld* World = WorldContext.World(); // 获取世界
	UGameInstance* GameInstance = WorldContext.OwningGameInstance; // 获取游戏实例
	FPerContextData& ActiveData = ContextData.FindOrAdd(ChangeContext); // 查找或添加上下文数据

	if ((GameInstance != nullptr) && (World != nullptr) && World->IsGameWorld()) // 检查游戏实例和世界是否有效
	{
		if (UGameFrameworkComponentManager* ComponentMan = UGameInstance::GetSubsystem<UGameFrameworkComponentManager>(GameInstance)) // 获取组件管理器
		{			
			int32 EntryIndex = 0; // 条目索引
			for (const FGameFeatureAbilitiesEntry& Entry : AbilitiesList) // 遍历能力列表
			{
				if (!Entry.ActorClass.IsNull()) // 检查Actor类是否有效
				{
					UGameFrameworkComponentManager::FExtensionHandlerDelegate AddAbilitiesDelegate = UGameFrameworkComponentManager::FExtensionHandlerDelegate::CreateUObject( // 创建扩展处理委托
						this, &UGameFeatureAction_AddAbilities::HandleActorExtension, EntryIndex, ChangeContext); // 绑定到处理函数
					TSharedPtr<FComponentRequestHandle> ExtensionRequestHandle = ComponentMan->AddExtensionHandler(Entry.ActorClass, AddAbilitiesDelegate); // 添加扩展处理器

					ActiveData.ComponentRequests.Add(ExtensionRequestHandle); // 添加组件请求
					EntryIndex++; // 递增条目索引
				}
			}
		}
	}
}

/**
 * 重置数据的方法
 */
void UGameFeatureAction_AddAbilities::Reset(FPerContextData& ActiveData)
{
	while (!ActiveData.ActiveExtensions.IsEmpty()) // 当活跃扩展不为空时
	{
		auto ExtensionIt = ActiveData.ActiveExtensions.CreateIterator(); // 创建迭代器
		RemoveActorAbilities(ExtensionIt->Key, ActiveData); // 移除Actor能力
	}

	ActiveData.ComponentRequests.Empty(); // 清空组件请求
}

/**
 * 处理Actor扩展的方法
 */
void UGameFeatureAction_AddAbilities::HandleActorExtension(AActor* Actor, FName EventName, int32 EntryIndex, FGameFeatureStateChangeContext ChangeContext)
{
	FPerContextData* ActiveData = ContextData.Find(ChangeContext); // 查找上下文数据
	if (AbilitiesList.IsValidIndex(EntryIndex) && ActiveData) // 检查索引有效且数据存在
	{
		const FGameFeatureAbilitiesEntry& Entry = AbilitiesList[EntryIndex]; // 获取条目
		if ((EventName == UGameFrameworkComponentManager::NAME_ExtensionRemoved) || (EventName == UGameFrameworkComponentManager::NAME_ReceiverRemoved)) // 检查是否是移除事件
		{
			RemoveActorAbilities(Actor, *ActiveData); // 移除Actor能力
		}
		else if ((EventName == UGameFrameworkComponentManager::NAME_ExtensionAdded) || (EventName == ALyraPlayerState::NAME_LyraAbilityReady)) // 检查是否是添加事件
		{
			AddActorAbilities(Actor, Entry, *ActiveData); // 添加Actor能力
		}
	}
}

/**
 * 添加Actor能力的方法
 */
void UGameFeatureAction_AddAbilities::AddActorAbilities(AActor* Actor, const FGameFeatureAbilitiesEntry& AbilitiesEntry, FPerContextData& ActiveData)
{
	check(Actor); // 检查Actor有效
	if (!Actor->HasAuthority()) // 检查是否有权限
	{
		return; // 无权限则返回
	}

	// 如果Actor已经应用了能力扩展，则提前返回
	if (ActiveData.ActiveExtensions.Find(Actor) != nullptr) // 检查是否已存在扩展
	{
		return;	// 已存在则返回
	}

	if (UAbilitySystemComponent* AbilitySystemComponent = FindOrAddComponentForActor<UAbilitySystemComponent>(Actor, AbilitiesEntry, ActiveData)) // 查找或添加能力系统组件
	{
		FActorExtensions AddedExtensions; // 创建添加的扩展
		AddedExtensions.Abilities.Reserve(AbilitiesEntry.GrantedAbilities.Num()); // 预分配能力数组空间
		AddedExtensions.Attributes.Reserve(AbilitiesEntry.GrantedAttributes.Num()); // 预分配属性数组空间
		AddedExtensions.AbilitySetHandles.Reserve(AbilitiesEntry.GrantedAbilitySets.Num()); // 预分配能力集句柄数组空间

		for (const FLyraAbilityGrant& Ability : AbilitiesEntry.GrantedAbilities) // 遍历授予的能力
		{
			if (!Ability.AbilityType.IsNull()) // 检查能力类型有效
			{
				FGameplayAbilitySpec NewAbilitySpec(Ability.AbilityType.LoadSynchronous()); // 创建能力规格
				FGameplayAbilitySpecHandle AbilityHandle = AbilitySystemComponent->GiveAbility(NewAbilitySpec); // 授予能力并获取句柄

				AddedExtensions.Abilities.Add(AbilityHandle); // 添加能力句柄
			}
		}

		for (const FLyraAttributeSetGrant& Attributes : AbilitiesEntry.GrantedAttributes) // 遍历授予的属性
		{
			if (!Attributes.AttributeSetType.IsNull()) // 检查属性集类型有效
			{
				TSubclassOf<UAttributeSet> SetType = Attributes.AttributeSetType.LoadSynchronous(); // 加载属性集类型
				if (SetType) // 检查类型有效
				{
					UAttributeSet* NewSet = NewObject<UAttributeSet>(AbilitySystemComponent->GetOwner(), SetType); // 创建新的属性集
					if (!Attributes.InitializationData.IsNull()) // 检查初始化数据有效
					{
						UDataTable* InitData = Attributes.InitializationData.LoadSynchronous(); // 加载初始化数据
						if (InitData) // 检查数据有效
						{
							NewSet->InitFromMetaDataTable(InitData); // 从元数据表初始化
						}
					}

					AddedExtensions.Attributes.Add(NewSet); // 添加属性集
					AbilitySystemComponent->AddAttributeSetSubobject(NewSet); // 添加属性集子对象
				}
			}
		}

		ULyraAbilitySystemComponent* LyraASC = CastChecked<ULyraAbilitySystemComponent>(AbilitySystemComponent); // 转换为Lyra能力系统组件
		for (const TSoftObjectPtr<const ULyraAbilitySet>& SetPtr : AbilitiesEntry.GrantedAbilitySets) // 遍历授予的能力集
		{
			if (const ULyraAbilitySet* Set = SetPtr.Get()) // 获取能力集
			{
				Set->GiveToAbilitySystem(LyraASC, &AddedExtensions.AbilitySetHandles.AddDefaulted_GetRef()); // 授予给能力系统
			}
		}

		ActiveData.ActiveExtensions.Add(Actor, AddedExtensions); // 添加活跃扩展
	}
	else
	{
		UE_LOG(LogGameFeatures, Error, TEXT("未能找到/添加能力组件到'%s'。能力将不会被授予。"), *Actor->GetPathName()); // 记录错误日志
	}
}

/**
 * 移除Actor能力的方法
 */
void UGameFeatureAction_AddAbilities::RemoveActorAbilities(AActor* Actor, FPerContextData& ActiveData)
{
	if (FActorExtensions* ActorExtensions = ActiveData.ActiveExtensions.Find(Actor)) // 查找Actor扩展
	{
		if (UAbilitySystemComponent* AbilitySystemComponent = Actor->FindComponentByClass<UAbilitySystemComponent>()) // 查找能力系统组件
		{
			for (UAttributeSet* AttribSetInstance : ActorExtensions->Attributes) // 遍历属性集实例
			{
				AbilitySystemComponent->RemoveSpawnedAttribute(AttribSetInstance); // 移除生成的属性
			}

			for (FGameplayAbilitySpecHandle AbilityHandle : ActorExtensions->Abilities) // 遍历能力句柄
			{
				AbilitySystemComponent->SetRemoveAbilityOnEnd(AbilityHandle); // 设置结束时移除能力
			}

			ULyraAbilitySystemComponent* LyraASC = CastChecked<ULyraAbilitySystemComponent>(AbilitySystemComponent); // 转换为Lyra能力系统组件
			for (FLyraAbilitySet_GrantedHandles& SetHandle : ActorExtensions->AbilitySetHandles) // 遍历能力集句柄
			{
				SetHandle.TakeFromAbilitySystem(LyraASC); // 从能力系统移除
			}
		}

		ActiveData.ActiveExtensions.Remove(Actor); // 移除活跃扩展
	}
}

/**
 * 查找或为Actor添加组件的方法
 */
UActorComponent* UGameFeatureAction_AddAbilities::FindOrAddComponentForActor(UClass* ComponentType, AActor* Actor, const FGameFeatureAbilitiesEntry& AbilitiesEntry, FPerContextData& ActiveData)
{
	UActorComponent* Component = Actor->FindComponentByClass(ComponentType); // 查找组件
	
	bool bMakeComponentRequest = (Component == nullptr); // 是否需要创建组件请求
	if (Component) // 如果组件存在
	{
		// 检查此组件是否来自不同的`UGameFrameworkComponentManager`请求
		// `Native`是动态添加组件的`CreationMethod`默认值
		if (Component->CreationMethod == EComponentCreationMethod::Native) // 检查创建方法是否为Native
		{
			// 尝试区分真正的原生组件和由GameFrameworkComponent系统创建的组件
			// 如果来自UGameFrameworkComponentManager，则需要发出另一个请求（请求是引用计数的）
			UObject* ComponentArchetype = Component->GetArchetype(); // 获取组件原型
			bMakeComponentRequest = ComponentArchetype->HasAnyFlags(RF_ClassDefaultObject); // 检查是否有类默认对象标志
		}
	}

	if (bMakeComponentRequest) // 如果需要创建组件请求
	{
		UWorld* World = Actor->GetWorld(); // 获取世界
		UGameInstance* GameInstance = World->GetGameInstance(); // 获取游戏实例

		if (UGameFrameworkComponentManager* ComponentMan = UGameInstance::GetSubsystem<UGameFrameworkComponentManager>(GameInstance)) // 获取组件管理器
		{
			TSharedPtr<FComponentRequestHandle> RequestHandle = ComponentMan->AddComponentRequest(AbilitiesEntry.ActorClass, ComponentType); // 添加组件请求
			ActiveData.ComponentRequests.Add(RequestHandle); // 添加组件请求句柄
		}

		if (!Component) // 如果组件仍然不存在
		{
			Component = Actor->FindComponentByClass(ComponentType); // 再次查找组件
			ensureAlways(Component); // 确保组件存在
		}
	}

	return Component; // 返回组件
}

#undef LOCTEXT_NAMESPACE // 取消定义本地化文本命名空间